package com.kkshop.service.impl;

import java.io.Serializable;
import java.util.List;

import org.apache.log4j.Logger;

import com.kkshop.dao.AbstractDAO;
import com.kkshop.domain.Persistent;
import com.kkshop.service.PersistenceService;
import com.kkshop.service.ServiceException;

public class PersistenceServiceImpl implements PersistenceService {
    
    private static final Logger log = Logger.getLogger(PersistenceServiceImpl.class);
    
    private List<AbstractDAO<Serializable, Persistent<? extends Serializable>>> daos;
    
    public Persistent<? extends Serializable> find(Class<? extends Persistent<? extends Serializable>> clazz, Serializable key) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("Finding model object of type " + clazz + " with primary key " + key + "...");
        }
        
        Persistent<? extends Serializable> result = getDao(clazz).findByPrimaryKey(key);
        
        if(log.isDebugEnabled()) {
            log.debug("Finding model object of type " + clazz + " with primary key " + key + " done");
        }
        
    	return result;
    }
    
    public List<? extends Persistent<? extends Serializable>> findAll(Class<? extends Persistent<? extends Serializable>> clazz) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("Finding all model objects of type " + clazz + "...");
        }
        
        List<? extends Persistent<? extends Serializable>> result =  getDao(clazz).findAll();
        
        if(log.isDebugEnabled()) {
            log.debug("Finding all model objects of type " + clazz + " done");
        }
        
        return result;
    }
    
    public void save(Persistent<? extends Serializable> model) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("Saving model object " + model + "...");
        }
        
    	getDao(model.getClass()).save(model);
    	
    	if(log.isDebugEnabled()) {
    	    log.debug("Saving model object " + model + " done");
    	}
    }
    
    public void update(Persistent<? extends Serializable> model) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("Updating model object " + model + "...");
        }
        
        getDao(model.getClass()).update(model);
        
        if(log.isDebugEnabled()) {
            log.debug("Updating model object " + model + " done");
        }
    }
    
    public void delete(Persistent<? extends Serializable> model) throws Exception {
        if(log.isDebugEnabled()) {
            log.debug("Deleting model object " + model + "...");
        }
        
    	getDao(model.getClass()).delete(model);
    	
    	if(log.isDebugEnabled()) {
            log.debug("Deleting model object " + model + " done");
        }
    }
    
    private AbstractDAO<Serializable, Persistent<? extends Serializable>> getDao(Class clazz) throws ServiceException {
        for (AbstractDAO<Serializable, Persistent<? extends Serializable>> dao : daos) {
            if(dao.getPersistentClass().isAssignableFrom(clazz)) {
                if(log.isDebugEnabled()) {
                    log.debug(dao + " will handle " + clazz);
                }
                return dao;
            }
        }
        
    	String message = "Could not find DAO for " + clazz.getName();
    	if(log.isDebugEnabled()) {
    	    log.error(message);
    	}
    	throw new ServiceException(message);
    }

    public List<AbstractDAO<Serializable, Persistent<? extends Serializable>>> getDaos() {
        return daos;
    }

    public void setDaos(
            List<AbstractDAO<Serializable, Persistent<? extends Serializable>>> daos) {
        this.daos = daos;
    }
}
